#ifndef __WIZ_GEOMETRY_AABB_HPP__SHANHAOBO_19800429__
#define __WIZ_GEOMETRY_AABB_HPP__SHANHAOBO_19800429__

#include "../Box/WizGeometryBoxAxisAligned.hpp"
#include "./WizGeometryBounding.hpp"

namespace Wiz
{
    namespace AABB
    {
        template<typename ElementT>
        struct Type : public ::Wiz::Bounding::Type< ::Wiz::AABox::Type<ElementT> >
        {
            typedef ElementT                        tElement;
            typedef tElement&                       tElementRef;
            typedef const tElement&                 tElementIn;

            typedef ::Wiz::Vector3::Type<tElement>  tVector3;

            WIZ_DECLARE_IO_WITHNAME(tVector3, tVector3);
            WIZ_DECLARE_REF_WITHNAME(tVector3, tVector3);

            typedef ::Wiz::Bounding::Type< ::Wiz::AABox::Type<ElementT> >   tSuper;

            ::Wiz::Bool::Type Build(::Wiz::UInt::In PntNum, const tVector3* PntArray)
            {
                this->SetNull();

                this->AddPointArray(PntNum, PntArray);
            }

            ::Wiz::Bool::Type AddPointArray(::Wiz::UInt::In PntNum, const tVector3* PntArray)
            {
                if (PntNum < 2)
                {
                    WIZ_ASSERT(::Wiz::Bool::False);
                    return ::Wiz::Bool::False;
                }
                ::Wiz::UInt::Type i;
                SetSafe(PntArray[0], PntArray[1]);
                for (i = 2; i < PntNum; i++)
                {
                    this->Expand(PntArray[i]);
                }
            }
        };

        namespace RV
        {
            template<typename ElementT>
            struct Type : public ::Wiz::AABB::Type<ElementT>
            {
                typedef ::Wiz::Matrix44::RowMajor::Type<tElement>   tMatrix44;
                ::Wiz::Void::Type Transform(tSuper& OutAABB, const tMatrix44& TM) const
                {
                    tCorners m_Corners;

                    OutAABB.GetAllCorners(m_Corners);
                    OutAABB.SetNull();
                    ::Wiz::Int::Type i;
                    OutAABB.SetSafe(m_Corners[0] * TM, m_Corners[1] * TM);
                    for (i = 2; i < ::Wiz::Box::Corner::eCornersCount; i++)
                    {
                        OutAABB.Expand(m_Corners[i] * TM);
                    }
                }
            };
        } /// end of namespace RV

        namespace CV
        {
            template<typename ElementT>
            struct Type : public ::Wiz::AABB::Type<ElementT>
            {
                typedef ::Wiz::Matrix44::ColMajor::Type<tElement>   tMatrix44;
                ::Wiz::Void::Type Transform(tSuper& OutAABB, const tMatrix44& TM) const
                {
                    tCorners m_Corners;

                    OutAABB.GetAllCorners(m_Corners);
                    OutAABB.SetNull();
                    ::Wiz::Int::Type i;
                    OutAABB.SetSafe(TM * m_Corners[0], TM * m_Corners[1]);
                    for (i = 2; i < ::Wiz::Box::Corner::eCornersCount; i++)
                    {
                        OutAABB.Expand(TM * m_Corners[i]);
                    }
                }
            }; /// end of struct Type
        } /// end of namespace CV
    } /// end of namespace AABB
} /// end of namespace Wiz

#endif /*__WIZ_GEOMETRY_AABB_HPP__SHANHAOBO_19800429__*/
